﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using XL_ModbusRtu;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private XL_ModbusRtu.ModbusRtu _modbusRtu;
        public Form1()
        {
            InitializeComponent();
        }
        private Stopwatch _stopwatch = new Stopwatch();
        private void But_Open_Click(object sender, EventArgs e)
        {
            if (But_Open.Text == "打 开")
            {
                ICommunications comm = Check_NetworkPort.Checked ? new XLTCP(1, TxtSeriarPort.Text, Convert.ToInt32(TxtPort.Text)) : new XLSerialPort(1, TxtSeriarPort.Text, Convert.ToInt32(TxtPort.Text)); 
                _modbusRtu = new XL_ModbusRtu.ModbusRtu(1, comm);
                _modbusRtu.Open();
                But_Open.Text = "关 闭";
            }
            else
            {
                But_Open.Text = "打 开";
                _modbusRtu.Close();
                Log("关闭串口通信");
            }
        }

        private void Log(string str)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() => TxtResponse.AppendText($"时间：{DateTime.Now:G}==>>{str}\r\n")));
                return;
            }
            TxtResponse.AppendText($"时间：{DateTime.Now:G}==>>{str}\r\n");
        }

        private void ButInteraction_Click(object sender, EventArgs e)
        {
            ButInteraction.Enabled = false;
            Interaction();
            ButInteraction.Enabled = true;
        }

        private void Interaction()
        {
            try
            {
                _stopwatch.Restart();
                string types = (ComFunction.InvokeRequired ? (string)ComFunction.Invoke(new Func<string>(() => ComFunction.Text)) : ComFunction.Text);
                switch (types)
                {
                    case "0x01":
                        //读线圈
                        if (string.IsNullOrEmpty(TxtLength.Text) || Convert.ToInt32(TxtLength.Text) == 0)
                        {
                            Log(_modbusRtu.GetCoil(Convert.ToInt32(TxtAddress.Text, 16)).ToString());
                        }
                        else
                        {
                            Log(string.Join("-", _modbusRtu.GetCoil(Convert.ToInt32(TxtAddress.Text, 16), Convert.ToInt32(TxtLength.Text))));
                        }
                        break;
                    case "0x05":
                        Log(_modbusRtu.SetCoil(Convert.ToInt32(TxtAddress.Text, 16), TxtValue.Text == "true" || TxtValue.Text == "1") ? "写线圈成功" : "写线圈失败");
                        break;
                    case "0x0F":
                        //写多线圈
                        bool[] bl = TxtValue.Text.Split("\r\n").Select(x => x == "true" || x == "1").ToArray();
                        Log(_modbusRtu.SetCoil(Convert.ToInt32(TxtAddress.Text, 16), bl).ToString());
                        break;
                    case "0x02":
                        //读离散量输入
                        if (string.IsNullOrEmpty(TxtLength.Text) || Convert.ToInt32(TxtLength.Text) == 0)
                        {
                            Log(_modbusRtu.GetDiscreteInput(Convert.ToInt32(TxtAddress.Text, 16)).ToString());
                        }
                        else
                        {
                            Log(string.Join("-", _modbusRtu.GetDiscreteInput(Convert.ToInt32(TxtAddress.Text, 16), Convert.ToInt32(TxtLength.Text))));
                        }
                        break;
                    case "0x03":
                        //读保持寄存器
                            Log(string.Join("-", _modbusRtu.ReadRegister(Convert.ToInt32(TxtAddress.Text, 16), (string.IsNullOrEmpty(TxtLength.Text) || Convert.ToInt32(TxtLength.Text) == 0) ? 1 : Convert.ToInt32(TxtLength.Text))));
                        break;
                    case "0x04":
                        //读输入寄存器
                        if (string.IsNullOrEmpty(TxtLength.Text) || Convert.ToInt32(TxtLength.Text) == 0)
                        {
                            Log(_modbusRtu.ReadInputRegister(Convert.ToInt32(TxtAddress.Text, 16)).ToString());
                        }
                        else
                        {
                            Log(string.Join("-", _modbusRtu.ReadInputRegister(Convert.ToInt32(TxtAddress.Text, 16), Convert.ToInt32(TxtLength.Text))));
                        }
                        break;
                    case "0x06":
                        //写单个寄存器
                        Log(_modbusRtu.SetRegister(Convert.ToInt32(TxtAddress.Text, 16), Convert.ToUInt16(TxtValue.Text)).ToString());
                        break;
                    case "0x10":
                        //写多个寄存器
                        ushort[] ushorts = TxtValue.Text.Split("\r\n").Select(x => Convert.ToUInt16(x)).ToArray();
                        Log(_modbusRtu.SetRegister(Convert.ToInt32(TxtAddress.Text, 16), ushorts).ToString());
                        break;
                }
                _stopwatch.Stop();
                Log($"耗时：{_stopwatch.ElapsedMilliseconds} ms");
            }
            catch (Exception ex)
            {
                Log($"交互异常：{ex}");
            }
        }

        private bool isContinuousReading;
        private void ButContinuousReading_Click(object sender, EventArgs e)
        {
            if (ButContinuousReading.Text == "开 始")
            {
                ButContinuousReading.Text = "停 止";
                isContinuousReading = true;
                But_Open.Enabled = false;
                ButInteraction.Enabled = false;
                Task.Run(() =>
                {
                    while (isContinuousReading)
                    {
                        try
                        {
                            Interaction();
                        }
                        catch (Exception ex)
                        {
                            Log($"循环异常：{ex}");
                        }
                        Thread.Sleep(20);
                    }
                    ButInteraction.Invoke(new Action(() => { ButInteraction.Enabled = true; But_Open.Enabled = true; }));
                });
            }
            else
            {
                isContinuousReading = false;
                ButContinuousReading.Text = "开 始";
            }

        }
    }
}
